home *** CD-ROM | disk | FTP | other *** search
/ Delphi Magazine Collection 2001 / Delphi Magazine Collection 20001 (2001).iso / DISKS / Issue69 / System / DesktopManager.pas < prev   
Encoding:
Pascal/Delphi Source File  |  2001-03-17  |  8.0 KB  |  233 lines

  1. unit DesktopManager;
  2.  
  3. interface
  4.  
  5. uses
  6.   Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs;
  7.  
  8. type
  9.   EDesktopManager = class (Exception);
  10.  
  11.   TDesktopManager = class(TComponent)
  12.   private
  13.     { Private declarations }
  14.     fActive: Boolean;                           // true if injected
  15.     fResponse: PChar;                           // response buffer
  16.     fDeskWin: hWnd;                             // handle of DLL's dialog window
  17.     fAppWindow: hWnd;                           // our window for receiving DLL messages
  18.     fGotResponse: Integer;                      // simple response flag to spin on
  19.     fDummyInteger: Integer;                     // for dummy property writes
  20.     procedure SetActive (Value: Boolean);
  21.     function GetItemCount: Integer;
  22.     function GetColor (Index: Integer): TColorRef;
  23.     procedure SetColor (Index: Integer; Value: TColorRef);
  24.     function GetCaption (Index: Integer): String;
  25.     function GetPosition (Index: Integer): TPoint;
  26.     procedure SetCaption (Index: Integer; const Value: String);
  27.     procedure SetPosition (Index: Integer; Value: TPoint);
  28.     function GetBoundingRectangle (Index: Integer): TRect;
  29.     function PendOnDeskTopMessage (Msg, wParam, lParam: Integer): PChar;
  30.   protected
  31.     { Protected declarations }
  32.     procedure RedrawItems (Forced: Boolean);
  33.     procedure RedrawSingleItem (Index: Integer);
  34.     procedure NeedActive;
  35.     procedure ReceiverHook (var Msg: TMessage); virtual;
  36.   public
  37.     { Public declarations }
  38.     constructor Create (AOwner: TComponent); override;
  39.     destructor Destroy; override;
  40.     property Caption [Index: Integer]: String read GetCaption write SetCaption;
  41.     property Position [Index: Integer]: TPoint read GetPosition write SetPosition;
  42.     property BoundingRectangle [Index: Integer]: TRect read GetBoundingRectangle;
  43.   published
  44.     { Published declarations }
  45.     property Active: Boolean read fActive write SetActive default False;
  46.     property ItemCount: Integer read GetItemCount write fDummyInteger stored False;
  47.     property TextColor: TColorRef index 0 read GetColor write SetColor stored False;
  48.     property BackgroundColor: TColorRef index 1 read GetColor write SetColor stored False;
  49.   end;
  50.  
  51. procedure Register;
  52.  
  53. implementation
  54.  
  55. uses CommCtrl, DeskManMessages;
  56.  
  57. // Interface to DeskManager.DLL
  58.  
  59. function DeskManagerLoad (AppWindow: hWnd): Bool; stdcall; external 'DeskManager.dll';
  60. function DeskManagerUnload: Bool; stdcall; external 'DeskManager.dll';
  61. function DeskManagerListView: HWnd; stdcall; external 'DeskManager.dll';
  62. function DeskManagerShellThread: DWord; stdcall; external 'DeskManager.dll';
  63.  
  64. constructor TDesktopManager.Create (AOwner: TComponent);
  65. begin
  66.     Inherited Create (AOwner);
  67.     fAppWindow := AllocateHWnd (ReceiverHook);
  68. end;
  69.  
  70. destructor TDesktopManager.Destroy;
  71. begin
  72.     // Bow out gracefully...
  73.     SetActive (False);
  74.     DeallocateHWnd (fAppWindow);
  75.     ReallocMem (fResponse, 0);
  76.     Inherited Destroy;
  77. end;
  78.  
  79. procedure TDesktopManager.ReceiverHook (var Msg: TMessage);
  80. var
  81.     Message: TWMCopyData absolute Msg;
  82. begin
  83.     if (Message.Msg = wm_CopyData) and (Message.From = fDeskWin) then with Message, Message.CopyDataStruct^ do begin
  84.         ReallocMem (fResponse, cbData);
  85.         Move (lpData^, fResponse^, cbData);
  86.         fGotResponse := dwData;
  87.         Result := Integer (True);
  88.     end else Msg.Result := DefWindowProc (fAppWindow, Msg.Msg, Msg.WParam, Msg.LParam);
  89. end;
  90.  
  91. function TDesktopManager.PendOnDeskTopMessage (Msg, wParam, lParam: Integer): PChar;
  92. begin
  93.     fGotResponse := -1;
  94.     PostMessage (fDeskWin, Msg, wParam, lParam);
  95.     while fGotResponse <> Msg do Application.ProcessMessages;
  96.     Result := fResponse;
  97. end;
  98.  
  99. procedure TDesktopManager.RedrawSingleItem (Index: Integer);
  100. begin
  101.     SetPosition (Index, GetPosition (Index));  // Think about it...
  102. end;
  103.  
  104. procedure TDesktopManager.RedrawItems (Forced: Boolean);
  105. begin
  106.     if Forced then begin
  107.         ShowWindow (DeskManagerListView, sw_Hide);
  108.         ShowWindow (DeskManagerListView, sw_ShowNormal);
  109.     end else begin
  110.         SendMessage (DeskManagerListView, lvm_RedrawItems, 0, GetItemCount - 1);
  111.         UpdateWindow (DeskManagerListView);
  112.     end;
  113. end;
  114.  
  115. procedure TDesktopManager.NeedActive;
  116. begin
  117.     if not fActive then
  118.         raise EDesktopManager.Create ('Desktop Manager is not active');
  119. end;
  120.  
  121. procedure TDesktopManager.SetActive (Value: Boolean);
  122. var
  123.     Msg: TMsg;
  124. begin
  125.     if fActive <> Value then begin
  126.         if Value then begin
  127.             if FindWindow (Nil, 'Delphi Desktop 2001') <> 0 then raise EDesktopManager.Create ('Another instance of ' + ClassName + ' is already active.') else begin
  128.                 DeskManagerLoad (fAppWindow);
  129.                 GetMessage (Msg, fAppWindow, DM_DLLReady, DM_DLLReady);
  130.                 fDeskWin := FindWindow (Nil, 'Delphi Desktop 2001');
  131.                 if fDeskWin = 0 then raise EDesktopManager.Create ('DLL initialization failed');
  132.                 fActive := True;
  133.             end;
  134.         end else begin
  135.             SendMessage (fDeskWin, wm_Close, 0, 0);
  136.             while IsWindow (fDeskWin) do Application.ProcessMessages;
  137.             DeskManagerUnload;
  138.             fActive := False;
  139.         end;
  140.     end;
  141. end;
  142.  
  143. function TDesktopManager.GetItemCount: Integer;
  144. begin
  145.     Result := ListView_GetItemCount (DeskManagerListView);
  146. end;
  147.  
  148. function TDesktopManager.GetColor (Index: Integer): TColorRef;
  149. begin
  150.     Result := 0;
  151.     case Index of
  152.         0:  Result := ListView_GetTextColor (DeskManagerListView);
  153.         1:  Result := ListView_GetTextBkColor (DeskManagerListView);
  154.     end;
  155. end;
  156.  
  157. procedure TDesktopManager.SetColor (Index: Integer; Value: TColorRef);
  158. begin
  159.     if GetColor (Index) <> Value then begin
  160.         case Index of
  161.             0:  ListView_SetTextColor (DeskManagerListView, Value);
  162.             1:  ListView_SetTextBkColor (DeskManagerListView, Value);
  163.         end;
  164.  
  165.         RedrawItems ((Value = CLR_None) and (Index = 1));
  166.     end;
  167. end;
  168.  
  169. function TDesktopManager.GetCaption (Index: Integer): String;
  170. begin
  171.     NeedActive;
  172.     if (Index < 0) or (Index >= GetItemCount) then Result := '' else
  173.         Result := StrPas (PendOnDesktopMessage (DM_GetItemText, Index, 0));
  174. end;
  175.  
  176. procedure TDesktopManager.SetCaption (Index: Integer; const Value: String);
  177. var
  178.     cds: TCopyDataStruct;
  179.     buff: array [0..255] of Char;
  180.     Idx: Integer absolute buff;
  181. begin
  182.     NeedActive;
  183.     if (Index >= 0) and (Index < GetItemCount) then begin
  184.         Idx := Index;
  185.         StrPCopy (@buff [sizeof (Integer)], Value);
  186.         cds.dwData := DM_SetItemText;
  187.         cds.cbData := Length (Value) + 1 + sizeof (Integer);
  188.         cds.lpData := @buff;
  189.         SendMessage (fDeskWin, WM_CopyData, fAppWindow, Integer (@cds));
  190.         RedrawSingleItem (Index);
  191.     end;
  192. end;
  193.  
  194. function TDesktopManager.GetBoundingRectangle (Index: Integer): TRect;
  195. begin
  196.     NeedActive;
  197.     if (Index < 0) or (Index >= GetItemCount) then SetRectEmpty (Result) else
  198.         Result := PRect (PendOnDesktopMessage (DM_GetItemRect, Index, 0))^;
  199. end;
  200.  
  201. function TDesktopManager.GetPosition (Index: Integer): TPoint;
  202. begin
  203.     NeedActive;
  204.     if (Index < 0) or (Index >= GetItemCount) then Result := Point (-1, -1) else
  205.         Result := PPoint (PendOnDesktopMessage (DM_GetItemPosition, Index, 0))^;
  206. end;
  207.  
  208. procedure TDesktopManager.SetPosition (Index: Integer; Value: TPoint);
  209. var
  210.     r: TRect;
  211. begin
  212.     NeedActive;
  213.     if (Index >= 0) and (Index < GetItemCount) then begin
  214.         r := GetBoundingRectangle (Index);
  215.         ListView_SetItemPosition (DeskManagerListView, Index, -1000, -1000);
  216.         InvalidateRect (DeskManagerListView, @r, True);
  217.         UpdateWindow (DeskManagerListView);
  218.         ListView_SetItemPosition (DeskManagerListView, Index, Value.x, Value.y);
  219.         r := GetBoundingRectangle (Index);
  220.         InvalidateRect (DeskManagerListView, @r, True);
  221.         UpdateWindow (DeskManagerListView);
  222.     end;
  223. end;
  224.  
  225. procedure Register;
  226. begin
  227.     RegisterComponents('Delphi Magazine', [TDesktopManager]);
  228. end;
  229.  
  230. end.
  231.  
  232.  
  233.